package com.childenglish.utils;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 数据加密工具类
 * 提供敏感数据加密和解密功能
 */
public class DataEncryptionUtils {

    private static final Logger logger = LoggerFactory.getLogger(DataEncryptionUtils.class);
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
    
    // 从环境变量或配置获取密钥，默认使用固定密钥（生产环境应使用环境变量）
    private static final String DEFAULT_SECRET_KEY = System.getenv("DATA_ENCRYPTION_KEY") != null 
        ? System.getenv("DATA_ENCRYPTION_KEY") 
        : "ChildEnglishPlatform2024SecretKey!@#$%^&*()";

    /**
     * 使用AES加密数据
     */
    public static String encrypt(String data) {
        if (data == null || data.isEmpty()) {
            return data;
        }
        try {
            SecretKeySpec secretKey = getSecretKey();
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            logger.error("数据加密失败", e);
            throw new RuntimeException("数据加密失败", e);
        }
    }

    /**
     * 使用AES解密数据
     */
    public static String decrypt(String encryptedData) {
        if (encryptedData == null || encryptedData.isEmpty()) {
            return encryptedData;
        }
        try {
            SecretKeySpec secretKey = getSecretKey();
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("数据解密失败", e);
            throw new RuntimeException("数据解密失败", e);
        }
    }

    /**
     * 生成密钥
     */
    private static SecretKeySpec getSecretKey() {
        try {
            // 使用SHA-256哈希确保密钥长度为256位
            java.security.MessageDigest sha = java.security.MessageDigest.getInstance("SHA-256");
            byte[] key = DEFAULT_SECRET_KEY.getBytes(StandardCharsets.UTF_8);
            key = sha.digest(key);
            return new SecretKeySpec(key, ALGORITHM);
        } catch (Exception e) {
            logger.error("生成密钥失败", e);
            throw new RuntimeException("生成密钥失败", e);
        }
    }

    /**
     * 使用Jasypt加密（用于配置文件等）
     */
    public static StringEncryptor getJasyptEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(System.getenv("JASYPT_ENCRYPTOR_PASSWORD") != null 
            ? System.getenv("JASYPT_ENCRYPTOR_PASSWORD") 
            : "defaultEncryptKey");
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

    /**
     * 加密敏感字段（如手机号、邮箱等）
     */
    public static String encryptSensitiveField(String field) {
        if (field == null || field.isEmpty()) {
            return field;
        }
        // 对于敏感字段，使用AES加密
        return encrypt(field);
    }

    /**
     * 解密敏感字段
     * 如果字段未加密（明文），直接返回原值
     */
    public static String decryptSensitiveField(String encryptedField) {
        if (encryptedField == null || encryptedField.isEmpty()) {
            return encryptedField;
        }
        try {
            // 首先检查是否是有效的Base64编码（加密数据应该是Base64格式）
            // Base64编码只包含 A-Z, a-z, 0-9, +, /, = 字符
            String base64Pattern = "^[A-Za-z0-9+/]*={0,2}$";
            if (!encryptedField.matches(base64Pattern)) {
                // 不是Base64格式，可能是明文，直接返回
                logger.debug("字段不是Base64格式，可能是明文: {}", encryptedField.substring(0, Math.min(10, encryptedField.length())) + "...");
                return encryptedField;
            }
            
            // 直接进行解密操作，以便捕获具体的加密异常
            SecretKeySpec secretKey = getSecretKey();
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedField));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (IllegalArgumentException e) {
            // Base64解码失败，可能是明文
            logger.debug("Base64解码失败，可能是明文: {}", e.getMessage());
            return encryptedField;
        } catch (javax.crypto.IllegalBlockSizeException e) {
            // 数据块大小不正确，可能是明文或未正确加密
            logger.debug("解密数据块大小不正确，可能是明文: {}", e.getMessage());
            return encryptedField;
        } catch (javax.crypto.BadPaddingException e) {
            // 填充错误，可能是明文或密钥不匹配
            logger.debug("解密填充错误，可能是明文: {}", e.getMessage());
            return encryptedField;
        } catch (Exception e) {
            // 其他解密错误，可能是明文或格式不正确
            logger.debug("解密敏感字段失败，可能未加密: {}", e.getMessage());
            return encryptedField; // 如果解密失败，返回原值（可能是未加密的数据）
        }
    }

    /**
     * 生成随机密钥（用于一次性加密）
     */
    public static String generateRandomKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            keyGenerator.init(256, new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (Exception e) {
            logger.error("生成随机密钥失败", e);
            throw new RuntimeException("生成随机密钥失败", e);
        }
    }
}

